package com.hxzy.config.security;

import cn.hutool.core.date.DateUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.hxzy.common.consts.RedisConst;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 令牌服务
 */
@Service
public class TokenService {

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 创建jwt token
     * @param adminLoginVO
     * @return
     */
    public String createJwtToken(AdminLoginResp  adminLoginVO){
        String uuid= UUID.randomUUID().toString();
        adminLoginVO.setUuid(uuid);
        adminLoginVO.setExpired(DateUtil.offsetMinute(new Date(), RedisConst.ADMIN_LOGIN_EXPIRED_MINUTES));

        //向redis中写入值
        String redisKey= RedisConst.getRedisKey(RedisConst.ADMIN_LOGIN_KEY,uuid);
        this.redisTemplate.opsForValue().set(redisKey,adminLoginVO,RedisConst.ADMIN_LOGIN_EXPIRED_MINUTES, TimeUnit.MINUTES);

        //返回jwt令牌
        return uuidToJwt(uuid);
    }

    /**
     * 把uuid转换成为jwt
     * @param uuid
     * @return
     */
    private String uuidToJwt(String uuid){
        Map<String, Object> map = new HashMap<String, Object>() {
            private static final long serialVersionUID = 1L;
            {
                put("uuid", uuid);
            }
        };
        return JWTUtil.createToken(map, RedisConst.JWT_SECURITY.getBytes());
    }

    /**
     * 把jwt解析，取得里面的 uuid
     * @param jwtToken
     * @return
     */
    private String parseJwtToUUID(String jwtToken){
        final JWT jwt = JWTUtil.parseToken(jwtToken);
        Object uuid = jwt.getPayload("uuid");
        return uuid.toString();
    }

    /**
     * 验证令牌的有效性
     * @return
     */
    public AdminLoginResp validatorToken(String jwtToken){

        //判断令牌是否有Bearer前缀，如果有就要删除它
        if(jwtToken.startsWith("Bearer")){
            jwtToken=jwtToken.replace("Bearer","").trim();
        }

        //解析jwt
        String uuid=this.parseJwtToUUID(jwtToken);
        //组装rediskey
        String redisKey=RedisConst.getRedisKey(RedisConst.ADMIN_LOGIN_KEY,uuid);
        //查询
        Object obj = this.redisTemplate.opsForValue().get(redisKey);
        //找不到
        if(obj==null){
            return null;
        }
        //如果redis键的过期时间还剩下10分钟，这时候，我们可以再给这个redis续时
        AdminLoginResp adminLoginVO= (AdminLoginResp) obj;

        return adminLoginVO;
    }

    /**
     * 刷新令牌的时间
     * @param adminLoginVO
     */
    public void refreshToken(AdminLoginResp  adminLoginVO){
        long expiredTime=adminLoginVO.getExpired().getTime();
        long currentTime=System.currentTimeMillis();
        //令牌还有10分钟就要过期了
        if(expiredTime-currentTime<=1000L*60*10){
            adminLoginVO.setExpired(DateUtil.offsetMinute(new Date(),RedisConst.ADMIN_LOGIN_EXPIRED_MINUTES));
            //更新redis中的键的值
            //向redis中写入值
            String redisKey= RedisConst.getRedisKey(RedisConst.ADMIN_LOGIN_KEY,adminLoginVO.getUuid());
            this.redisTemplate.opsForValue().set(redisKey,adminLoginVO,RedisConst.ADMIN_LOGIN_EXPIRED_MINUTES, TimeUnit.MINUTES);

        }
    }


}
